#ifndef _VL_THREAD_POOL__H_
#define _VL_THREAD_POOL__H_


#include <mutex>
#include <memory>
#include <functional>
#include <condition_variable>
#include <vector>
#include <thread>
#include <queue>
#include "vl_future.h"

namespace VL {

/**
 * @Author: CimZzz
 * @Date: 2022-08-27 16:39:19
 * 
 * 预声明线程池
 */
class VLThreadPool;

/**
 * @Author: CimZzz
 * @Date: 2022-08-27 16:39:28
 * 
 * 声明 Buffer
 */
class Buffer;

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 15:06:37
 * 
 * 线程 Functor
 */
class VLThreadRunnable {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 14:39:23
	 * 
	 * 可执行回调
	 */
	using Runnable = std::function<void()>;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:05:54
	 * 
	 * 携带 Future 的可执行回调
	 */
	using FutureRunnable = std::function<void(const std::shared_ptr<VLFuture>&)>;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 14:39:23
	 * 
	 * 可执行回调, 使用 Buffer
	 */
	using RunnableWithBuffer = std::function<void(Buffer*)>;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:05:54
	 * 
	 * 携带 Future 的可执行回调, 使用 Buffer
	 */
	using FutureRunnableWithBuffer = std::function<void(const std::shared_ptr<VLFuture>&, Buffer*)>;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:11:24
	 * 
	 * 构造方法
	 * 
	 * @param runnable 可执行回调
	 */
	explicit VLThreadRunnable(Runnable runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:11:46
	 * 
	 * 构造方法
	 * 
	 * @param runnable 携带 Future 的可执行回调
	 */
	explicit VLThreadRunnable(FutureRunnable runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:11:24
	 * 
	 * 构造方法
	 * 
	 * @param runnable 可执行回调, 使用 Buffer
	 */
	explicit VLThreadRunnable(RunnableWithBuffer runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:11:46
	 * 
	 * 构造方法
	 * 
	 * @param runnable 携带 Future 的可执行回调, 使用 Buffer
	 */
	explicit VLThreadRunnable(FutureRunnableWithBuffer runnable);


private:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:09:54
	 * 
	 * 线程执行方法
	 */
	void threadRun();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:41:45
	 * 
	 * 中断
	 */
	void interrupt();

	friend class VLThreadPool;

	Buffer* buffer;
	Runnable runnable;
	FutureRunnable futureRunnable;
	RunnableWithBuffer runnableWithBuffer;
	FutureRunnableWithBuffer futureRunnableWithBuffer;
	std::shared_ptr<VLFuture> futurePtr;
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 16:25:30
 * 
 * 线程 Future 管理器
 */
class ThreadFutureManager {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:25:55
	 * 
	 * 构造函数
	 */
	explicit ThreadFutureManager();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:27:44
	 * 
	 * 获取数据, 否则抛出异常
	 */
	void getOrThrow();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:26:58
	 * 
	 * 添加 Future
	 * 
	 * @param futurePtr Future 指针
	 */
	void addFuture(const std::shared_ptr<VLFuture>& futurePtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 16:27:09
	 * 
	 * 获取 Future
	 * 
	 * @param index Future 下标
	 * 
	 * @return Future 指针
	 */
	std::shared_ptr<VLFuture> getFuture(unsigned int index);

private:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 19:35:37
	 * 
	 * Future 列表
	 */
	std::vector<std::shared_ptr<VLFuture>> futureList;
};

class VLThreadPool;

/**
 * @Author: CimZzz
 * @Date: 2022-08-23 21:34:01
 * 
 * 临时线程
 */
class VLTempThread {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2023-02-28 11:02:52
	 * 
	 * 析构函数
	 */
	~VLTempThread();
private:
	friend class VLThreadPool;

	/**
	 * @Author: CimZzz
	 * @Date: 2023-02-28 11:02:58
	 * 
	 * 构造函数, 临时线程需要切换为类, 走析构函数
	 */
	VLTempThread();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 21:35:10
	 * 
	 * 当前临时线程是否正在运行中
	 */
	bool isRunning;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 21:35:24
	 * 
	 * 线程指针
	 */
	std::shared_ptr<std::thread> threadPtr;
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-21 01:06:04
 * 
 * 新版线程池
 */
class VLThreadPool {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 01:07:12
	 * 
	 * 构造函数
	 * 
	 * @param threadCount 常驻线程数
	 * @param tempCount 临时线程数
	 * @param tempKeepSeconds 临时线程持续时间, 单位秒
	 * 
	 * @note 当并发任务数超过常驻线程时, 线程池会开辟临时线程数来应对任务, 临时线程会持续一段时间后被回收
	 */
	explicit VLThreadPool(unsigned int threadCount, unsigned int tempCount = 0, unsigned int tempKeepSeconds = 10);


	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 01:08:04
	 * 
	 * 析构函数
	 */
	~VLThreadPool();


	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:10:39
	 * 
	 * 初始化线程池
	 * 
	 */
	void initThreadPool();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:12:41
	 * 
	 * 执行线程回调
	 * 
	 * @param runnable 线程回调
	 */
	void exec(VLThreadRunnable::Runnable runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:12:41
	 * 
	 * 执行线程回调
	 * 
	 * @param runnable 线程回调
	 */
	void exec(VLThreadRunnable::RunnableWithBuffer runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:13:57
	 * 
	 * 执行 Future 线程回调
	 * 
	 * @param runnable 线程回调
	 * 
	 * @return Future 指针
	 */
	template<typename T, typename E>
	std::shared_ptr<VLFuture> exec(VLThreadRunnable::FutureRunnable runnable) {
		auto ptr = std::shared_ptr<VLThreadRunnable>(new VLThreadRunnable(runnable));
		auto futurePtr = VLFuture::newFuture<T, E>();
		ptr->futurePtr = futurePtr;
		this->exec(ptr);
		return futurePtr;
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:13:57
	 * 
	 * 执行 Future 线程回调
	 * 
	 * @param runnable 线程回调
	 * 
	 * @return Future 指针
	 */
	template<typename T, typename E>
	std::shared_ptr<VLFuture> exec(VLThreadRunnable::FutureRunnableWithBuffer runnable) {
		auto ptr = std::shared_ptr<VLThreadRunnable>(new VLThreadRunnable(runnable));
		auto futurePtr = VLFuture::newFuture<T, E>();
		ptr->futurePtr = futurePtr;
		this->exec(ptr);
		return futurePtr;
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:58:00
	 * 
	 * 等待全部任务完成
	 */
	void waitForAllTaskDone();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 17:07:33
	 * 
	 * 将后续任务添加到等待队列中
	 */
	void pendingTask();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 17:07:51
	 * 
	 * 将等待队列中的任务放置到主消息队列中
	 */
	void continueTask();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:14:57
	 * 
	 * 中断线程池中其他任务
	 */
	void clearTask();

private: 

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 21:03:14
	 * 
	 * 添加常驻线程
	 */
	void addThread();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 21:05:50
	 * 
	 * 添加临时线程
	 */
	void addTempThread();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 21:45:05
	 * 
	 * 检查是否需要添加新的临时线程
	 */
	void checkNeedTempThread();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:40:01
	 * 
	 * 执行线程回调
	 * 
	 * @param runnable 线程回调
	 */
	void exec(const std::shared_ptr<VLThreadRunnable>& runnable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:32:06
	 * 
	 * 是否正在运行中
	 */
	volatile bool isRunning;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 01:08:34
	 * 
	 * 是否已经初始化完成
	 */
	bool isInit;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 17:08:23
	 * 
	 * 判断当前是否需要进行等待队列
	 */
	bool isPending;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 19:36:54
	 * 
	 * 常驻线程数
	 */
	uint32_t threadCount;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 19:37:11
	 * 
	 * 允许临时线程数
	 */
	uint32_t tempCount;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 19:37:46
	 * 
	 * 临时线程存在时间
	 */
	uint32_t tempKeepSeconds;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 20:35:43
	 * 
	 * 当前常驻线程繁忙数
	 */
	volatile uint32_t curThreadCount;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 19:42:22
	 * 
	 * 当前临时线程繁忙数
	 */
	volatile uint32_t curTempCount;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:55:56
	 * 
	 * 任务数
	 */
	volatile uint32_t taskCount;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-24 08:09:02
	 * 
	 * 未处理任务数
	 */
	volatile uint32_t unprocessedTaskCount;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:29:04
	 * 
	 * 线程锁
	 */
	std::mutex mutex;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:29:15
	 * 
	 * 条件变量
	 */
	std::condition_variable cond;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-21 15:57:35
	 * 
	 * 任务全部完成条件变量
	 */
	std::condition_variable taskDoneCond;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:22:41
	 * 
	 * 线程池列表
	 */
	std::vector<std::shared_ptr<std::thread>> threadList;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-23 19:42:50
	 * 
	 * 临时线程池列表
	 */
	std::vector<std::shared_ptr<VLTempThread>> tempThreadList;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:38:08
	 * 
	 * 可执行回调队列
	 */
	std::queue<std::shared_ptr<VLThreadRunnable>> runnableQueue;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-06-23 15:38:08
	 * 
	 * 可执行回调等待队列
	 */
	std::queue<std::shared_ptr<VLThreadRunnable>> pendingQueue;
};

}

#endif // _VL_THREAD_POOL__H_
